package org.jeik.utils;

import org.apache.commons.codec.binary.Base64;

// CIPHER / GENERATORS
import javax.crypto.Cipher;
import javax.crypto.SecretKey;

// KEY SPECIFICATIONS
import java.security.spec.KeySpec;
import java.security.spec.AlgorithmParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEParameterSpec;

// EXCEPTIONS
import java.security.InvalidAlgorithmParameterException;
import java.security.NoSuchAlgorithmException;
import java.security.InvalidKeyException;
import java.security.spec.InvalidKeySpecException;
import javax.crypto.NoSuchPaddingException;

/**
 * 
 * @author AAsha
 */
public final class StringEncrypter {

	//
	private Cipher ecipher;
	private Cipher dcipher;
	
	/**
	 * 
	 * @param key
	 * @param algorithm
	 */
	public StringEncrypter(SecretKey key, String algorithm) {
		try {
			ecipher = Cipher.getInstance(algorithm);
			dcipher = Cipher.getInstance(algorithm);
			ecipher.init(Cipher.ENCRYPT_MODE, key);
			dcipher.init(Cipher.DECRYPT_MODE, key);
		} catch (NoSuchPaddingException e) {
			e.printStackTrace();
			Log.error(this, e.getMessage());
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
			Log.error(this, e.getMessage());
		} catch (InvalidKeyException e) {
			e.printStackTrace();
			Log.error(this, e.getMessage());
		}
	}
	
	/**
	 * 
	 * @param passPhrase
	 */
	public StringEncrypter(String passPhrase) {

		byte[] salt = { (byte) 0xA9, (byte) 0x9B, (byte) 0xC8, (byte) 0x32,
				(byte) 0x56, (byte) 0x34, (byte) 0xE3, (byte) 0x03 };

		int iterationCount = 19;

		try {

			KeySpec keySpec = new PBEKeySpec(passPhrase.toCharArray(), salt,
					iterationCount);
			SecretKey key = SecretKeyFactory.getInstance("PBEWithMD5AndDES")
					.generateSecret(keySpec);

			ecipher = Cipher.getInstance(key.getAlgorithm());
			dcipher = Cipher.getInstance(key.getAlgorithm());

			AlgorithmParameterSpec paramSpec = new PBEParameterSpec(salt,
					iterationCount);

			ecipher.init(Cipher.ENCRYPT_MODE, key, paramSpec);
			dcipher.init(Cipher.DECRYPT_MODE, key, paramSpec);

		} catch (InvalidAlgorithmParameterException e) {
			e.printStackTrace();
			Log.error(this, e.getMessage());
		} catch (InvalidKeySpecException e) {
			e.printStackTrace();
			Log.error(this, e.getMessage());
		} catch (NoSuchPaddingException e) {
			e.printStackTrace();
			Log.error(this, e.getMessage());
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
			Log.error(this, e.getMessage());
		} catch (InvalidKeyException e) {
			e.printStackTrace();
			Log.error(this, e.getMessage());
		}
	}
	
	/**
	 * 
	 * @param str
	 * @return
	 */
	public String encrypt(String str) {
		try {
			byte[] utf8 = str.getBytes("UTF8");

			byte[] enc = ecipher.doFinal(utf8);

			return Base64.encodeBase64String(enc);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}
	
	/**
	 * 
	 * @param str
	 * @return
	 */
	public String decrypt(String str) {
		try {
			byte[] dec = Base64.decodeBase64(str);

			byte[] utf8 = dcipher.doFinal(dec);

			return new String(utf8, "UTF8");
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}
}